package application

import (
	"context"
	"github.com/edgexfoundry/edgex-go/internal/app/core/metadata/container"
	m "github.com/edgexfoundry/edgex-go/internal/app/models"
	"github.com/edgexfoundry/edgex-go/internal/app/pkg/controller/http"
	"github.com/edgexfoundry/edgex-go/internal/pkg/correlation"
	bootstrapContainer "github.com/edgexfoundry/go-mod-bootstrap/v2/bootstrap/container"
	"github.com/edgexfoundry/go-mod-bootstrap/v2/di"
	"github.com/edgexfoundry/go-mod-core-contracts/v2/errors"
)

func DeviceResourceAdd(deviceId string, resource m.DeviceResource, ctx context.Context, dic *di.Container) errors.EdgeX {
	dbClient := container.DBClientFrom(dic.Get)
	lc := bootstrapContainer.LoggingClientFrom(dic.Get)

	_, err := dbClient.DeviceResourceAdd(deviceId, resource)
	if err != nil {
		return errors.NewCommonEdgeXWrapper(err)
	}

	lc.Debugf("DeviceProfile deviceResources added on DB successfully. Correlation-id: %s ", correlation.FromContext(ctx))

	go SyncDeviceProfileById(deviceId, ctx, dic)
	return nil
}

func DeviceResourceDelete(deviceId, id string, ctx context.Context, dic *di.Container) errors.EdgeX {

	if id == "" {
		return errors.NewCommonEdgeX(errors.KindNaNError, http.DeviceIdNotNull, nil)
	}

	dbClient := container.DBClientFrom(dic.Get)
	lc := bootstrapContainer.LoggingClientFrom(dic.Get)

	exist, err := dbClient.DeviceIdExists(deviceId)
	if err != nil {
		return errors.NewCommonEdgeXWrapper(err)
	} else if !exist {
		return errors.NewCommonEdgeX(errors.KindInvalidId, http.DeviceNotExist, nil)
	}

	_, err = dbClient.DeviceResourceDelete(deviceId, id)
	if err != nil {
		return errors.NewCommonEdgeXWrapper(err)
	}

	lc.Debugf("Device deviceResources deleted on DB successfully. Correlation-id: %s ", correlation.FromContext(ctx))
	go SyncDeviceProfileById(deviceId, ctx, dic)
	return nil
}

func DeviceResourceUpdate(deviceId string, dr m.DeviceResource, ctx context.Context, dic *di.Container) errors.EdgeX {
	if dr.Name == "" {
		return errors.NewCommonEdgeX(errors.KindNaNError, http.DeviceNameNotNull, nil)
	}
	dbClient := container.DBClientFrom(dic.Get)
	lc := bootstrapContainer.LoggingClientFrom(dic.Get)

	exist, err := dbClient.DeviceIdExists(deviceId)
	if err != nil {
		return errors.NewCommonEdgeXWrapper(err)
	} else if !exist {
		return errors.NewCommonEdgeX(errors.KindInvalidId, http.DeviceNotExist, nil)
	}

	_, err = dbClient.DeviceResourceUpdate(deviceId, dr)
	if err != nil {
		return errors.NewCommonEdgeXWrapper(err)
	}

	lc.Debugf("Device deviceResources deleted on DB successfully. Correlation-id: %s ", correlation.FromContext(ctx))
	go SyncDeviceProfileById(deviceId, ctx, dic)
	return nil
}

func DeviceResourcesGetByDeviceId(deviceId string, offset, limit int, ctx context.Context, dic *di.Container) (resources []m.DeviceResource, totalCount uint32, e errors.EdgeX) {
	dbClient := container.DBClientFrom(dic.Get)
	lc := bootstrapContainer.LoggingClientFrom(dic.Get)

	exist, err := dbClient.DeviceIdExists(deviceId)
	if err != nil {
		return resources, totalCount, errors.NewCommonEdgeXWrapper(err)
	} else if !exist {
		return resources, totalCount, errors.NewCommonEdgeX(errors.KindInvalidId, http.DeviceNotExist, nil)
	}

	lc.Debugf("Device deviceResources deleted on DB successfully. Correlation-id: %s ", correlation.FromContext(ctx))
	return dbClient.DeviceResourcesGetByDeviceId(deviceId, offset, limit)
}
